/*
 * @Author: yangzonglong
 * @Date: 2021-05-14 18:53:32
 * @version: v1.0.0
 * @Descripttion: 条件设置
 * @LastEditors: yangzonglong
 * @LastEditTime: 2021-05-17 14:22:50
 * @Auditor: 
 */
import React, { useState, useEffect, useContext, useCallback, useRef } from 'react';
import { Select, Input } from 'antd';
import { Icon, units } from '@library';
import context from '../context';
import { BPMN_NODE_TYPE, createBpmnXMLNode } from './../../../utils/bpmnUtils';
import style from './../style.module.scss';
import { GateConditionVarProps, SequenceFlowSelfProps, FormField, StartEventSelfProps, UserTaskSelfProps } from './../../../interface';
import CustJS from './_CustJS';

type Type = 'and' | 'or';

const $t = window.$app.t;
// const controlTypes = ['int', 'float', 'number', 'amount'];
const selectStyle = { width: '60px', minWidth: '60px' }

const judges = [
  { value: '>', label: $t('greaterThan') },
  { value: '<', label: $t('lessThan') },
  { value: '>=', label: $t('greaterThanOrEqualTo') },
  { value: '<=', label: $t('lessThanOrEqualTo') },
  { value: '===', label: $t('beEqualTo') },
  { value: '!==', label: $t('notEqualTo') }
]

// const judges1 = [
//   { value: '===', label: $t('beEqualTo') },
//   { value: '!==', label: $t('notEqualTo') }
// ]

export default () => {
  const isInitSelf = useRef(false);
  const { modeler, self } = useContext(context);
  const [andGate, setAndGate] = useState<GateConditionVarProps[]>([])
  const [orGate, setOrGate] = useState<GateConditionVarProps[]>([]);
  const [vars, setVars] = useState<FormField[]>([]);
  const [userTask, setUserTask] = useState<UserTaskSelfProps[]>([]); // 动作时 用户可选的userTask

  const _self = self as SequenceFlowSelfProps;

  useEffect(() => {
    const values = _self.businessObject?.extensionElements?.values;
    const amdGate = values?.[0].values || [];
    const orGate = values?.[1].values || [];

    if(amdGate.length) setAndGate(amdGate);
    else setAndGate([{ variableContext: 'global' }] as any);
    
    if(orGate.length) setOrGate(orGate);
    else setOrGate([{ variableContext: 'global' }] as any);

    const children = _self.parent?.children || [];
    const startEvent = children.find(item => item.type === BPMN_NODE_TYPE.START_EVENT);
    setVars((startEvent as StartEventSelfProps)?.businessObject?.extensionElements?.values?.[0]?.values || []);

    const list: UserTaskSelfProps[] = [];

    const getBpmnElement = (id: string) => {
      let item = children.find(item => item.id === id) as any;

      switch (item.type) {
        case BPMN_NODE_TYPE.SEQUENCE_FLOW: {
          if ((item as SequenceFlowSelfProps)?.source?.id) {
            getBpmnElement((item as SequenceFlowSelfProps).source!.id)
          }
          break
        }

        case BPMN_NODE_TYPE.EXCLUSIVE_GATEWAY: {
          for (let i of item.incoming) getBpmnElement(i.id)
          break
        }

        case BPMN_NODE_TYPE.USER_TASK: {
          list.push(item)
          break
        }

        case BPMN_NODE_TYPE.PARALLEL_GATEWAY: {
          for (let i of item.incoming) getBpmnElement(i.id)
          break
        }

      }
    }

    getBpmnElement(_self.id as string);
    setUserTask(list);

    setTimeout(() => isInitSelf.current = true, 500);
  }, [_self]);

  useEffect(() => {
    if(!isInitSelf.current) return;

    _self.businessObject!.extensionElements = Object.assign(createBpmnXMLNode(modeler, BPMN_NODE_TYPE.EXTENSION_ELEMENTS), {
      values: [
        Object.assign(createBpmnXMLNode(modeler, BPMN_NODE_TYPE.HL_ANDGATE_CONDITION_VAR), {
          values: andGate.map(item => {
            const copyItem = { ...item };
            if(copyItem.$type) delete copyItem.$type;
            return Object.assign(createBpmnXMLNode(modeler, BPMN_NODE_TYPE.HL_CONDITION), copyItem)
          })
        }),
        Object.assign(createBpmnXMLNode(modeler, BPMN_NODE_TYPE.HL_ORGATE_CONDITION_VAR), {
          values: orGate.map(item => {
            const copyItem = { ...item };
            if(copyItem.$type) delete copyItem.$type;
            return Object.assign(createBpmnXMLNode(modeler,BPMN_NODE_TYPE.HL_CONDITION), copyItem)
          })
        })
      ],
    })
  }, [andGate, orGate, _self, modeler]);

  const getGate = useCallback((type: Type) => {
    if (type === 'and') return { gate: andGate, setGate: setAndGate };
    return { gate: orGate, setGate: setOrGate }
  }, [andGate, orGate]);

  const onChange = useCallback((type: Type, cindex: number, value: any) => {
    const { gate, setGate } = getGate(type);
    setGate(gate.map((item, index) => {
      if (index === cindex) {
        return { ...item, ...value } // 本次修改的 合并值
      }
      return item;
    }))
  }, [getGate]);
  console.log(andGate);
  const onChangeField = useCallback((e, type: Type, index: number) => {
    const currVar = vars.find(item => item.fieldName === e)!;
    onChange(type, index, {
      fieldName: currVar.fieldName,
      term: '',
      variableId: currVar.controlId,
      variableType: currVar.type,
      variableName: currVar.name
    })
  }, [vars, onChange]);

  const onChangeTerm = useCallback((e, type: Type, index: number) => {
    onChange(type, index, { term: e })
  }, [onChange]);

  const onChangeContext = useCallback((e, type: Type, index: number) => {
    onChange(type, index, {
      variableContext: e,
      fieldName: '',
      term: '',
      variableId: '',
      variableType: '',
      variableName: '',
      comparesValue: ''
    })
  }, [onChange]);

  // 删除一条
  const remove = useCallback((type: Type, cindex: number) => {
    const { gate, setGate } = getGate(type);

    if (gate.length > 1) {
      return setGate(gate.filter((item, index) => index !== cindex))
    }

    onChange(type, cindex, {
      fieldName: '',
      term: '',
      comparesValue: '',
      variableName: '',
      variableId: ''
    })
  }, [getGate, onChange]);

  // 添加一条
  const add = useCallback((type: Type) => {
    const { gate, setGate } = getGate(type);

    const some = gate.some(item => !item.variableId && !item.fieldName);
    if (some) return units.message.warning('添加错误');

    setGate(gate.concat({ variableContext: type === 'and' ? 'global' : 'button' } as any));
  }, [getGate]);

  const onChangeComparesValue = useCallback((e, type: Type, cindex: number) => {
    onChange(type, cindex, { comparesValue: e.target.value })
  }, [onChange]);

  const getActionSelectData = useCallback((type: Type, index: number) => {
    const { gate } = getGate(type);
    const curGate = gate[index];

    const curUserTask = userTask.find(item => item.id === curGate.variableId);
    const actionData = curUserTask?.businessObject?.extensionElements?.values?.[0]?.values || [];
    return actionData
  }, [getGate, userTask]);

  const onChangeVariableId = useCallback((e, type: Type, index: number) => {
    const { gate } = getGate(type);

    const some = gate.some(item => item.variableId === e); // variableId 唯一
    if (some) return units.message.warning('重复节点条件');

    const data = userTask.find(item => item.id === e)!;

    onChange(type, index, {
      fieldName: '',
      term: '===',
      variableId: data.id,
      comparesValue: data.id,
      variableType: data.type,
      variableName: data.businessObject?.name
    })
  }, [getGate, userTask, onChange]);

  const onChangeActionComparesValue = useCallback((e, type: Type, index: number   ) => {
    onChange(type, index, { comparesValue: e })
  }, [onChange]);
  console.log(userTask);
  const createItem = useCallback((item: GateConditionVarProps, type: Type, index: number) => {
    return (
      <li key={index}>
        <span>{type === 'and' ? '且' : '或'}</span>
        <Select style={selectStyle} value={item.variableContext} onChange={e => onChangeContext(e, type, index)}>
          <Select.Option value="global">{$t('global')}</Select.Option>
          <Select.Option value="button">{$t('motion')}</Select.Option>
        </Select>

        {item.variableContext === 'global' && (
          <>
            <Select style={selectStyle} value={item.fieldName} onChange={(e) => onChangeField(e, type, index)}>
              {vars.map(item => (
                <Select.Option key={item.fieldName} value={item.fieldName}>{item.name}</Select.Option>
              ))}
            </Select>
            <Select style={selectStyle} value={item.term} onChange={e => onChangeTerm(e, type, index)}>
              {/* {(controlTypes.includes(item.variableType) ? judges : judges1).map(item => (
                <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
              ))} */}
              {judges.map(item => (
                <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
              ))}
            </Select>
          </>
        )}

        {item.variableContext === 'button' && (
          <>
            <Select style={selectStyle} value={item.variableId} onChange={(e) => onChangeVariableId(e, type, index)}>
              {userTask.map(item => (
                <Select.Option key={item.id} value={item.id || ''}>{item.businessObject?.name}</Select.Option>
              ))}
            </Select>

            <Select style={selectStyle} value={item.comparesValue} onChange={e => onChangeActionComparesValue(e, type, index)}>
              {getActionSelectData(type, index).map(item => (
                <Select.Option key={item.action} value={item.action}>{item.label}</Select.Option>
              ))}
            </Select>
          </>
        )}

        <Input
          disabled={item.variableContext === 'button'}
          onChange={e => onChangeComparesValue(e, type, index)}
          value={item.comparesValue} />
        <Icon onClick={() => remove(type, index)} className={style.variableIcon} icon='&#xe633;' />
        <Icon onClick={() => add(type)} className={style.variableIcon} icon='&#xe635;' />
      </li>
    )
  }, [vars, add, onChangeField, onChangeContext, remove, userTask, onChangeActionComparesValue, onChangeVariableId, onChangeTerm, onChangeComparesValue, getActionSelectData]);

  return (
    <div>
      <p>条件设置</p>
      <ul className={style.variable}>
        {andGate.map((item, index) => createItem(item, 'and', index))}
      </ul>
      <div className={style.dividingLine} />
      <ul className={style.variable}>
        {orGate.map((item, index) => createItem(item, 'or', index))}
      </ul>

      <div className={style.dividingLine} />
      <CustJS andGate={andGate} orGate={orGate}/>
    </div>
  )
}